#include <interface\abstractSlideBar.h>
#include <interface\fieldSet.h>

#include <interface\window.h>

abstractBarCursor::abstractBarCursor(abstractSlideBar* par):    winElmt(),
                                                                parentBar(par){
    ELname = "<abstractBarCursor>";
}
abstractBarCursor::abstractBarCursor(abstractSlideBar* par,window* win):    winElmt(win),
                                                                            parentBar(par){
    ELname = "<abstractBarCursor>";
}
abstractBarCursor::~abstractBarCursor(){}

void abstractBarCursor::getOffset(int* xoff,int* yoff){
    parentBar->getPos(xoff,yoff);
    parentBar->getOffset(xoff,yoff);
    if( parentBar->getType() == sBar_horizontal ){
        *xoff += (int)((parentBar->getWidth() - getWidth())*parentBar->getPosition());
    }else{
        *yoff += (int)((parentBar->getHeight() - getHeight())*parentBar->getPosition());
    }
}

void abstractBarCursor::setPosition(int pos){
    int PoffX;
    int PoffY;
    long lval;
    long hval;
    parentBar->getPos(&PoffX,&PoffY);
    parentBar->getOffset(&PoffX,&PoffY);
    parentBar->getBounds(&lval,&hval);
    if( parentBar->getType() == sBar_horizontal ){
        parentBar->setValue( (long)((hval - lval) * ((float)pos - PoffX - getWidth()/2)/((float)parentBar->getWidth() - getWidth())) );
    }else{
        parentBar->setValue( (long)((hval - lval) * ((float)pos - PoffY - getHeight()/2)/((float)parentBar->getHeight() - getHeight())) );
    }
}

void abstractBarCursor::draggingEvent(int x,int y){
    if( parentBar->getType() == sBar_horizontal ){
        setPosition(oldX+x);
    }else{
        setPosition(oldY+y);
    }
}

abstractSlideBar::abstractSlideBar(sBar_type ty):   winElmt(),
                                                    type( ty ),
                                                    hiVal( 0 ),
                                                    loVal( 0 ),
                                                    value( 0 ),
                                                    cursor( new abstractBarCursor(this) ){
    ELname = "<abstractBar>";
}
abstractSlideBar::abstractSlideBar(sBar_type ty,window* win):   winElmt(win),
                                                                type( ty ),
                                                                hiVal( 0 ),
                                                                loVal( 0 ),
                                                                value( 0 ),
                                                                cursor( new abstractBarCursor(this, win) ){
    ELname = "<abstractBar>";
}
abstractSlideBar::~abstractSlideBar(){
    delete cursor;
}

void abstractSlideBar::setCursor(abstractBarCursor* curs){
    delete cursor;
    cursor = curs;
}

unsigned char abstractSlideBar::getType(){
    return type;
}

void abstractSlideBar::setBounds(long lo,long hi){
    if( hi < lo ) return;
    hiVal = hi;
    loVal = lo;
    if( value < lo ) value = lo;
    else if( value > hi ) value = hi;
    barChangeValueEvent();
}
void abstractSlideBar::getBounds(long* lo,long* hi){
    *lo = loVal;
    *hi = hiVal;
}
void abstractSlideBar::setValue(long val){
    if( val < loVal ) value = loVal;
    else if( val > hiVal ) value = hiVal;
    else value = val;
    barChangeValueEvent();
}
float abstractSlideBar::getPosition(){
    if( hiVal == loVal ) return 0;
    return ((float)(value - loVal))/((float)(hiVal-loVal));
}
long abstractSlideBar::getValue(){
    return value;
}

winElmt* abstractSlideBar::getCursorElem(){
    return cursor;
}

void abstractSlideBar::mouseClickEvent(int){
    if( type == sBar_horizontal ){
        cursor->setPosition( parentWin->getInput()->getMouseX() );
    }else{
        cursor->setPosition( parentWin->getInput()->getMouseY() );
    }
}

void abstractSlideBar::barChangeValueEvent(){}

unsigned char abstractSlideBar::eventExec( unsigned char in ){
    in = cursor->eventExec(in);
    if( active ){
        switch( parentWin->getInput()->bindRoll() ){
            case ROLL_UP:   setValue(value+1); break;
            case ROLL_DOWN: setValue(value-1); break;
        }
    }
    return winElmt::eventExec(in);
}
